package org.dragonfire.editor.tibasic;

import java.awt.Checkbox;

import org.dragonfire.editor.AttributeManager;
import org.dragonfire.editor.TIDocument;
import org.dragonfire.ti.TIFile;
import org.dragonfire.util.token.Token;
import org.dragonfire.util.token.TokenTable;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;

/**
 * An example showing how to create a multi-page editor. This example has 3
 * pages:
 * <ul>
 * <li>page 0 contains a nested text editor.
 * <li>page 1 allows you to change the font used in page 2
 * <li>page 2 shows the words in page 0 in sorted order
 * </ul>
 */
public class TIBasicEditor extends MultiPageEditorPart implements IResourceChangeListener {

	static {
		AttributeManager.addAttribute("tibasic.preview", new TextAttribute(null, null, SWT.NORMAL, new Font(Display
				.getCurrent(), "Courier New", 12, SWT.NORMAL)));
		AttributeManager.addAttribute("tibasic.source", new TextAttribute(null, null, SWT.NORMAL, new Font(Display
				.getCurrent(), "Courier New", 12, SWT.NORMAL)));
	}

	/** The text editor used in page 0. */
	private TIBasicSourceEditor sourceEditor;

	/** The font chosen in page 1. */
	private Font font;

	/** The text widget used in page 2. */
	private StyledText previewText;

	private ContentOutlinePage outline;

	private Text txtName;
	private Label lblDisplayName;
	private Checkbox chkProtected;

	/**
	 * Creates a multi-page editor example.
	 */
	public TIBasicEditor() {
		super();
		ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
	}

	/**
	 * Creates page 0 of the multi-page editor, which contains a text editor.
	 */
	void createSourceEditor() {
		try {
			sourceEditor = new TIBasicSourceEditor(this, TIFile.CALC_8X);

			int index = addPage(sourceEditor, getEditorInput());
			setPageText(index, "Source");
			setPartName(sourceEditor.getTitle());
		} catch (PartInitException e) {
			ErrorDialog.openError(getSite().getShell(), "Error creating nested text editor", null, e.getStatus());
		}
	}

	public IContentOutlinePage getContentOutlinePage() {
		if (outline == null)
			outline = new TIBasicOutlinePane(this);
		return outline;
	}

	public void updateTextAttributes() {
		TextAttribute preview = AttributeManager.getAttribute("tibasic.preview");
		previewText.setFont(preview.getFont());
		previewText.setBackground(preview.getBackground());
		previewText.setForeground(preview.getForeground());
		// TODO update sourceEditor font/text
	}

	public Object getAdapter(Class key) {
		if (key.equals(IContentOutlinePage.class)) {
			return showOutlineView() ? getContentOutlinePage() : null;
		}
		/*
		 * else if (key.equals(IPropertySheetPage.class)) { return
		 * getPropertySheetPage(); } else if (key.equals(IGotoMarker.class)) {
		 * return this; }
		 */
		else {
			return super.getAdapter(key);
		}
	}

	public boolean showOutlineView() {
		return true;
	}

	/**
	 * Creates page 1 of the multi-page editor, which allows you to change the
	 * font used in page 2.
	 */
	void createPropertiesEditor() {

		Composite composite = new Composite(getContainer(), SWT.NONE);
		GridLayout layout = new GridLayout();
		composite.setLayout(layout);
		layout.numColumns = 3;

		// Button fontButton = new Button(composite, SWT.NONE);
		GridData gd = new GridData(GridData.BEGINNING);
		gd.horizontalSpan = 1;
		Label lblName = new Label(composite, SWT.NONE);
		lblName.setText("Program name:");
		lblName.setLayoutData(gd);
		txtName = new Text(composite, SWT.SINGLE | SWT.LEFT);
		lblDisplayName = new Label(composite, SWT.NONE);
		lblDisplayName.setFont(AttributeManager.getAttribute("tibasic.preview").getFont());
		lblDisplayName.setLayoutData(gd);
		txtName.setLayoutData(gd);
		txtName.setBackground(new Color(Display.getCurrent(), 255, 255, 255));
		txtName.addListener(SWT.Modify, new Listener() {

			public void handleEvent(Event event) {
				TokenTable table = TIFile.getTokenTable(TIFile.CALC_8X);
				Token[] tokens = table.readTokens(txtName.getText());
				String text = "";
				for (Token t : tokens)
					text += t.getDisplayText();
				lblDisplayName.setText(text);
				if (sourceEditor != null && sourceEditor.getDocument() != null)
					((TIDocument) sourceEditor.getDocument()).setVarName(txtName.getText());
			}

		});
		if (sourceEditor != null && sourceEditor.getDocument() != null)
			txtName.setText(((TIDocument) sourceEditor.getDocument()).getVarName());
		Label lblProtected = new Label(composite, SWT.NONE);
		lblProtected.setText("Protected:");
		lblProtected.setLayoutData(gd);

		/*
		 * fontButton.setLayoutData(gd); fontButton.setText("Change Font...");
		 * fontButton.addSelectionListener(new SelectionAdapter() { public void
		 * widgetSelected(SelectionEvent event) { setFont(); } });
		 */

		int index = addPage(composite);
		setPageText(index, "Properties");
	}

	public StyledText getPreviewPage() {
		return previewText;
	}

	public int getActivePage() {
		return super.getActivePage();
	}

	/**
	 * Creates page 2 of the multi-page editor, which shows the sorted text.
	 */
	void createPreviewPage() {
		Composite composite = new Composite(getContainer(), SWT.NONE);
		FillLayout layout = new FillLayout();
		composite.setLayout(layout);
		previewText = new StyledText(composite, SWT.H_SCROLL | SWT.V_SCROLL);
		previewText.setEditable(false);
		int index = addPage(composite);
		setPageText(index, "Preview");
	}

	/**
	 * Creates the pages of the multi-page editor.
	 */
	protected void createPages() {
		createSourceEditor();
		createPreviewPage();
		createPropertiesEditor();
		updateTextAttributes();
	}

	/**
	 * The <code>MultiPageEditorPart</code> implementation of this
	 * <code>IWorkbenchPart</code> method disposes all nested editors.
	 * Subclasses may extend.
	 */
	public void dispose() {
		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
		super.dispose();
	}

	/**
	 * Saves the multi-page editor's document.
	 */
	public void doSave(IProgressMonitor monitor) {
		getEditor(0).doSave(monitor);
	}

	/**
	 * Saves the multi-page editor's document as another file. Also updates the
	 * text for page 0's tab, and updates this multi-page editor's input to
	 * correspond to the nested editor's.
	 */
	public void doSaveAs() {
		IEditorPart editor = getEditor(0);
		editor.doSaveAs();
		setPageText(0, editor.getTitle());
		setInput(editor.getEditorInput());
	}

	/*
	 * (non-Javadoc) Method declared on IEditorPart
	 */
	public void gotoMarker(IMarker marker) {
		setActivePage(0);
		IDE.gotoMarker(getEditor(0), marker);
	}

	/**
	 * The <code>MultiPageEditorExample</code> implementation of this method
	 * checks that the input is an instance of <code>IFileEditorInput</code>.
	 */
	public void init(IEditorSite site, IEditorInput editorInput) throws PartInitException {
		if (!(editorInput instanceof IFileEditorInput))
			throw new PartInitException("Invalid Input: Must be IFileEditorInput");

		super.init(site, editorInput);
	}

	/*
	 * (non-Javadoc) Method declared on IEditorPart.
	 */
	public boolean isSaveAsAllowed() {
		return true;
	}

	/**
	 * Calculates the contents of page 2 when the it is activated.
	 */
	protected void pageChange(int newPageIndex) {
		super.pageChange(newPageIndex);
		if (newPageIndex == 1) {
			TokenTable table = TIFile.getTokenTable(TIFile.CALC_8X);
			Token[] tokens = table.readTokens(sourceEditor.getDocument().get());
			String text = "";
			for (Token t : tokens)
				text += t.getDisplayText();
			text = text.replaceAll(" ", (char) 0xB7 + "");
			StyleRange sr = new StyleRange();
			previewText.setText(text);
		}
	}

	/**
	 * Closes all project files on project close.
	 */
	public void resourceChanged(final IResourceChangeEvent event) {
		if (event.getType() == IResourceChangeEvent.PRE_CLOSE) {
			Display.getDefault().asyncExec(new Runnable() {

				public void run() {
					IWorkbenchPage[] pages = getSite().getWorkbenchWindow().getPages();
					for (int i = 0; i < pages.length; i++) {
						if (((FileEditorInput) sourceEditor.getEditorInput()).getFile().getProject().equals(
								event.getResource())) {
							IEditorPart editorPart = pages[i].findEditor(sourceEditor.getEditorInput());
							pages[i].closeEditor(editorPart, true);
						}
					}
				}
			});
		}
	}

	public void untokenize(IDocument document) {
		String contents = document.get();

	}

	public TIBasicSourceEditor getSourceEditor() {
		return sourceEditor;
	}
}
